﻿/*
 * Copyright (c) 2008 Sculo, Yoann & Favréaux, Mathieu.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

using Lidgren.Library.Network;

namespace BBCommon
{
   // Type of messages
   public enum BBMsgType
   {
      ASK_LOGIN, OK_LOGIN, NO_LOGIN,
      CHAT, TYPING_MSG, KNOCK,
      SET_PLAYER_INFO, SET_ACTOR_INFO,
      ADD_MONSTER, DEL_MONSTER, ADD_PLAYER, DEL_PLAYER,
      ACTOR_SHOOT, ACTOR_SHOOT_RESPONSE,
      COFFEE, EAT, PRIVATE_MESSAGE, PRIVATE_CONVERSATION,
      JOIN_CONVERSATION, LEAVE_CONVERSATION,
      PENDU,
      PARAM1, PARAM2, PARAM3,
      VDM, BASH
   };

   // Message container
   [Serializable()]
   public class BBMessage
   {
      public static string Version = "2.2.1.5";

      // Message Type
      public BBMsgType MsgType;
      public BBConversation Conversation;

      // Associated datas
      public ActorRTInfo ActorInfo;
      public PlayerCarac PlayerCarac;
      public MonsterCarac MonsterCarac;

      public ShootDescription Shoot;
      public ShootResponseDesc Resp;

      public string Message;

      // Other datas
      public string Param1;
      public bool Param2;
      public int Param3;
      //Permet de savoir l'ID de la conversation
      public int Param4;

      // Serialization / Deserialization
      public NetMessage GetNetMessage()
      {
         MemoryStream s = new MemoryStream();
         BinaryFormatter b = new BinaryFormatter();
         b.Serialize(s, this);
         // WAY TOO BIG !!
         NetMessage netmsg = new NetMessage();
         s.Capacity = (int)s.Length;
         netmsg.Write(s.GetBuffer());

         return netmsg;
      }
      public static BBMessage FromNetMessage(NetMessage netmsg)
      {
         BBMessage msg = new BBMessage();
         MemoryStream s = new MemoryStream(netmsg.ReadBytes(netmsg.Length));
         s.Seek(0, SeekOrigin.Begin);
         BinaryFormatter b = new BinaryFormatter();
         msg = (BBMessage)b.Deserialize(s);

         return msg;
      }

      // Message creation
      public void MsgActorShoot(ShootDescription shoot)
      {
         Shoot = shoot;
         MsgType = BBMsgType.ACTOR_SHOOT;
      }

      public void MsgShootResponse(ShootResponseDesc resp)
      {
         Resp = resp;
         MsgType = BBMsgType.ACTOR_SHOOT_RESPONSE;
      }

      public void MsgAskLogin(PlayerCarac carac, string version)
      {
         PlayerCarac = carac;
         MsgType = BBMsgType.ASK_LOGIN;
         Param1 = version;
      }

      public void MsgOkLogin(int id)
      {
         PlayerCarac.ActorID = id;
         MsgType = BBMsgType.OK_LOGIN;
      }

      public void MsgNoLogin(string reason)
      {
         MsgType = BBMsgType.NO_LOGIN;
         Param1 = reason;
      }

      public void MsgChat(string text, PlayerCarac player)
      {
         MsgType = BBMsgType.CHAT;
         PlayerCarac = player;
         Message = text;
         Param1 = text;         
      }

      public void MsgChatVDM(string text, PlayerCarac player, bool displayMessage, BBMessage message)
      {
         MsgType = BBMsgType.VDM;
         Conversation = message.Conversation;
         PlayerCarac = player;
         Message = text;
         Param1 = text;
         Param2 = displayMessage;
      }

      public void MsgChatHelper(string text, PlayerCarac player, BBMessage message)
      {
         MsgType = BBMsgType.CHAT;
         Conversation = message.Conversation;
         PlayerCarac = player;
         Message = text;
         Param1 = text;         
      }

      public void MsgChatPendu(string text, PlayerCarac player, bool alert, BBMessage message)
      {
         MsgType = BBMsgType.PENDU;
         Conversation = message.Conversation;
         PlayerCarac = player;
         Message = text;
         Param1 = text;
         Param2 = alert;
      }

      public void MsgChatBash(string text, PlayerCarac player, bool toDisplay, BBMessage message)
      {
         MsgType = BBMsgType.BASH;
         Conversation = message.Conversation;
         PlayerCarac = player;
         Message = text;
         Param1 = text;
         Param2 = toDisplay;
      }

      public void MsgTypingMsg(bool isTypingNow)
      {
         MsgType = BBMsgType.TYPING_MSG;
         Param2 = isTypingNow;         
      }

      public void MsgKnock(string reason, int dest)
      {
         MsgType = BBMsgType.KNOCK;
         Param1 = reason;
         Param3 = dest;
      }

      public void MsgCoffee(string reason, int dest)
      {
         MsgType = BBMsgType.COFFEE;
         Param1 = reason;
         Param3 = dest;
      }

      public void MsgEat(string reason, int dest)
      {
         MsgType = BBMsgType.EAT;
         Param1 = reason;
         Param3 = dest;
      }

      public void MsgPrivateMessage(string text, string actualNickName)
      {
         MsgType = BBMsgType.PRIVATE_MESSAGE;
         Param1 = text;
         //Param3 = dest;

         if (this.Conversation != null)
         {
             if (!this.Conversation.LastTalker.Equals(actualNickName))
             {
                 this.Conversation.ChangeLastTalker = true;
             }
             else
             {
                 this.Conversation.ChangeLastTalker = false;
             }

             this.Conversation.LastTalker = actualNickName;
         }
      }

      public void MsgPrivateConversation(string text, int dest)
      {
         MsgType = BBMsgType.PRIVATE_CONVERSATION;
         Param1 = text;
         Param3 = dest;
      }

      public void MsgAddPlayer(Player player, bool newplayer)
      {
         PlayerCarac = player.Carac;
         ActorInfo = player.Info;
         Param2 = newplayer;
         MsgType = BBMsgType.ADD_PLAYER;
      }

      public void MsgJoinConversationPlayer(Player player, bool newplayer)
      {
          PlayerCarac = player.Carac;
          ActorInfo = player.Info;
          Param2 = newplayer;
          MsgType = BBMsgType.JOIN_CONVERSATION;
      }

      public void MsgLeaveConversationPlayer(int id, string reason)
      {
          PlayerCarac = new PlayerCarac();
          PlayerCarac.ActorID = id;
          Param1 = reason;
          MsgType = BBMsgType.LEAVE_CONVERSATION;
      }

      public void MsgDelPlayer(int id, string reason)
      {
         PlayerCarac = new PlayerCarac();
         PlayerCarac.ActorID = id;
         Param1 = reason;
         MsgType = BBMsgType.DEL_PLAYER;
      }      
   }

   [Serializable()]
   public class BBConversation : ISerializable
   {
      public static int LastConversationID = 0;

      private List<string> players;
      /// <summary>
      /// Obtient la liste des utilisateurs
      /// </summary>
      public List<string> Players
      {
         get { return players; }
         set { players = value; }
      }

      public long ConversGUID;
      public long ConversID;
      public string LastTalker;
      public bool ChangeLastTalker = false;

      private long FindRandomID(List<string> players)
      {
         int count = new Random().Next(100000, 999999);

         //Nombre aléatoire         
         foreach (string str in players)
         {
            count += str.Length;
            count += DateTime.Now.Second;
         }

         string tmp = string.Concat(DateTime.Now.Hour.ToString(), DateTime.Now.Minute.ToString(), DateTime.Now.Second.ToString(), count.ToString());

         if (tmp.Length > 16)
            tmp = tmp.Substring(0, 16);

         return Int64.Parse(tmp);
      }

      public BBConversation(List<string> players)
      {
         this.ConversID = this.FindRandomID(players);
         this.Players = players;
         this.ConversGUID = this.ConversID;
         this.LastTalker = string.Empty;          
      }

      public override string ToString()
      {
         string tmp = string.Empty;

         foreach (string str in this.Players)
         {
            string tmpstr = str;
               if (str.Length > 10)
                  tmpstr = str.Substring(0, 10);

               if (!string.IsNullOrEmpty(tmp))

                  tmp = string.Concat(tmp, "-", tmpstr);
               else
                  tmp = tmpstr;
         }

         return tmp;
      }

      #region ISerializable Members

      public void GetObjectData(SerializationInfo info, StreamingContext context)
      {
         info.AddValue("Players", this.Players);
         info.AddValue("ConversID", this.ConversID);
         info.AddValue("ConversGUID", this.ConversGUID);
         info.AddValue("LastTalker", this.LastTalker);
         info.AddValue("ChangeLastTalker", this.ChangeLastTalker);
      }

      public BBConversation(SerializationInfo info, StreamingContext context)
      {
         this.ConversID = info.GetInt64("ConversID");
         this.Players = info.GetValue("Players", typeof(List<string>)) as List<string>;
         this.ConversGUID = info.GetInt64("ConversGUID");
         this.LastTalker = info.GetString("LastTalker");
         this.ChangeLastTalker = info.GetBoolean("ChangeLastTalker");
      }

      #endregion
   }
}
